package main

import (
	"fmt"
	"log"

	"github.com/shopspring/decimal"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

type students struct {
	ID    uint   `gorm:"primaryKey" json:"id"`
	Name  string `gorm:"size:100 not null" json:"name"`
	Age   uint   `gorm:"size:100" json:"age"`
	Grade uint   `gorm:"size:2" json:"grade"`
}

// 插入
func (s *students) create(db *gorm.DB) error {
	result := db.Create(s)
	if result.Error != nil {
		return fmt.Errorf("插入失败: %v", result.Error)
	}
	return nil
}

// 查询
func (s *students) findAndPrint(db *gorm.DB) error {
	result := db.Where("age > ?", 18).Find(s) // 查询结果存储到接收者

	if result.Error != nil {
		return fmt.Errorf("查询失败: %v", result.Error)
	}

	// 检查是否找到记录
	if result.RowsAffected == 0 {
		return fmt.Errorf("未找到年龄大于18的学生记录")
	}

	// 打印查询到的学生信息
	fmt.Printf("找到学生: ID=%d, 姓名=%s, 年龄=%d, 年级=%d\n",
		s.ID, s.Name, s.Age, s.Grade)

	return nil
}

// 更新
func (s *students) update(db *gorm.DB) error {
	result := db.Model(&students{}).Where("id", 1).Update("name", "gine")
	if result.Error != nil {
		return fmt.Errorf("更新失败: %v", result.Error)
	}
	return nil
}

type Account struct {
	ID      uint            `gorm:"primaryKey" json:"id"`
	Balance decimal.Decimal `gorm:"decimal:10 not null" json:"balance"`
}
type Transaction struct {
	ID            uint            `gorm:"primaryKey" json:"id"`
	FromAccountId uint            `gorm:"size:11" json:"from_account_id"`
	ToAccountId   uint            `gorm:"size:11" json:"to_account_id"`
	Amount        decimal.Decimal `gorm:"DECIMAL(10,2) NOT NULL," json:"amount"`
}

// 事务操作
//func commit1(db *gorm.DB) error {
//	//编写一个事务，实现从账户 A 向账户 B 转账 100 元的操作。在事务中，需要先检查账户 A 的余额是否足够，如果足够则从账户 A 扣除 100 元，
//	//向账户 B 增加 100 元，并在 transactions 表中记录该笔转账信息。如果余额不足，则回滚事务。
//	err := db.Transaction(func(tx *gorm.DB) error {
//		accounts := &Account{}
//		result := db.Model(accounts).Where("id=?", 1).First(accounts)
//		if result.Error != nil {
//			return fmt.Errorf("查询失败: %v", result.Error)
//		}
//		intAsDecimal := decimal.NewFromInt(int64(100))
//		if !accounts.Balance.GreaterThanOrEqual(intAsDecimal) {
//			return fmt.Errorf("余额不足: 交易失败")
//		}
//		//更新表记录便且添加记录表
//		decBalance := accounts.Balance.Sub(intAsDecimal)
//		result = db.Model(accounts).Update("balance", decBalance)
//		if result.Error != nil {
//			return fmt.Errorf("更新失败: %v", result.Error)
//		}
//		//更新id为2加100
//		var accounts1 interface{}
//		result = obj.Where("id=?", 2).First(accounts1)
//		addBalance := accounts1.Balance.Add(intAsDecimal)
//		obj = db.Model(accounts1).Where("id=?", 2).Update("balance", addBalance)
//		if result.Error != nil {
//			return fmt.Errorf("更新失败: %v", result.Error)
//		}
//		//添加记录
//		db.Model(new(transactions)).Create(&transactions{
//			FromAccountId: 1,
//			ToAccountId:   2,
//			Amount:        intAsDecimal,
//		})
//		return nil
//	})
//	if err != nil {
//		return err
//	}
//	return nil
//}

func commit(db *gorm.DB) error {
	return db.Transaction(func(tx *gorm.DB) error {
		const transferAmount = 100
		amountDecimal := decimal.NewFromInt(transferAmount)

		// 1. 查询账户A并检查余额
		var accountA Account
		if err := tx.Where("id = ?", 1).First(&accountA).Error; err != nil {
			return fmt.Errorf("查询账户A失败: %w", err)
		}

		// 检查余额是否足够
		if accountA.Balance.LessThan(amountDecimal) {
			return fmt.Errorf("账户余额不足: 当前余额 %s, 需要 %s", accountA.Balance.String(), amountDecimal.String())
		}

		// 2. 查询账户B
		var accountB Account
		if err := tx.Where("id = ?", 2).First(&accountB).Error; err != nil {
			return fmt.Errorf("查询账户B失败: %w", err)
		}

		// 3. 更新账户A - 减少余额
		newBalanceA := accountA.Balance.Sub(amountDecimal)
		if err := tx.Model(&accountA).Update("balance", newBalanceA).Error; err != nil {
			return fmt.Errorf("更新账户A余额失败: %w", err)
		}

		// 4. 更新账户B - 增加余额
		newBalanceB := accountB.Balance.Add(amountDecimal)
		if err := tx.Model(&accountB).Update("balance", newBalanceB).Error; err != nil {
			return fmt.Errorf("更新账户B余额失败: %w", err)
		}

		// 5. 记录交易
		transaction := Transaction{
			FromAccountId: 1,
			ToAccountId:   2,
			Amount:        amountDecimal,
		}

		if err := tx.Create(&transaction).Error; err != nil {
			return fmt.Errorf("创建交易记录失败: %w", err)
		}

		return nil
	})
}

func main() {
	//链接数据库
	dsn := "root:root@tcp(127.0.0.1:3306)/gorm?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		log.Fatalf("数据库链接失败: %v", err)
	}
	studentObj := &students{
		Name:  "Jinzh",
		Grade: 1,
		Age:   1,
	}
	if studentObj.create(db) != nil {
		log.Fatalf("数据库插入失败: %v", err)
	}
	fmt.Println("数据插入成功")
	//查询
	sObj := new(students)
	res := sObj.findAndPrint(db)
	if res != nil {
		log.Fatalf("数据库查询失败: %v", err)
	}
	//更新数据
	err = sObj.update(db)
	if err != nil {
		log.Fatalf("数据库更新失败: %v", err)
	}
	//删除数据
	err = db.Delete(sObj, "age < ?", 15).Error
	if err != nil {
		log.Fatalf("数据库数据删除: %v", err)
	}
	fmt.Println("数删除成功")

	err = commit(db)
	if err != nil {
		log.Fatalf("转账失败: %v", err)
	}
	fmt.Println("交易成功")
}
